﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Extentions;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Authorization.Infrastructure;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json.Linq;
using TrainingReminderSystem.ApiControllers;
using TrainingReminderSystem.Bll;
using TrainingReminderSystem.Model;

namespace TrainingReminderSystem.Filters
{
    /// <summary>
    /// 验证登录用的
    /// </summary>
    public class ActionFilterAttributeLogin : ActionFilterAttribute
    {
        #region 新的验证  设置多语言,登录信息(权限验证)获取与验证,记录操作日志

        /// <summary>
        /// 新的验证
        /// </summary>
        /// <param name="context"></param>
        /// <param name="next"></param>
        /// <returns></returns>
        public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            #region 设置多语言

            LanguageHelper.SetLanguage();

            #endregion

            #region 设置OpenID 判断是否有WechatToken,有的话,自动登录

            if (PcLoginedBll.CurrentOpenID == null)
            {
                AjaxResult<List<LoginInfo>> ar = SysEmployeeOpenIDBll.LoginByToken();
                //成功,有登录信息,并且 没有Token值或有Token,但是用户信息有误 的时候,才会去让客户端写入Token值
                if (ar.Success && ar.Result != null && ar.Result.Count > 0 && (string.IsNullOrEmpty(PcLoginedBll.Token) || PcLoginedBll.CurrentEmployee == null))
                {
                    ar.Total = (int)EnumTotal.WeChatToken返回登录信息;
                    ContentResult cr = new ContentResult();
                    cr.Content = ar.ExToJson();
                    context.Result = cr;
                    return;
                }

                if (ar.Success == false)
                {
                    ar.Message += $" {lan(context).GetString("ActionFilter.LoginExpired")}";
                    ar.Total = (int)EnumTotal.WeChatToken错误;
                    ContentResult cr = new ContentResult();
                    cr.Content = ar.ExToJson();
                    context.Result = cr;
                    return;
                }
            }

            #endregion

            #region 验证直接通过的

            if (context.ActionDescriptor is not ControllerActionDescriptor controllerActionDescriptor)
            {
                await next();
                return;
            }
            var type = typeof(AllowAnonymousAttribute);
            bool isDefined = controllerActionDescriptor.ControllerTypeInfo.CustomAttributes.Any(m => m.AttributeType == type)
                || controllerActionDescriptor.MethodInfo.CustomAttributes.Any(m => m.AttributeType == type);
            if (isDefined)
            {
                await NextDo(context, next);
                return;
            }

            #endregion

            #region AccessToken的验证

            string controller = controllerActionDescriptor.RouteValues["controller"];
            var listControllerNames = new List<string>()
            {
                nameof(AccessTokenInfoController)
            };
            if (!string.IsNullOrEmpty(controller) && listControllerNames.Any(m => m.IndexOf(controller, StringComparison.OrdinalIgnoreCase) != -1))
            {
                //验证AccessToken是否有效,验证IP白名单的问题
                string accessToken = ExHttpContext.Current.Request.ExGetVal("accessToken");
                if (string.IsNullOrEmpty(accessToken))
                {
                    var post = ExHttpContext.Current.Request.ExBodyString();
                    //不能关闭流,不然的话,webapi的Action里面的值就获取不到了 //sr.Close();
                    var temp = JsonHelper.DeserializeObject(post) as JObject;
                    accessToken = temp.ExGetValue("AccessToken");
                }
                var ajaxResult = new SysAccessTokenInfoBll().ValidateAccessToken(accessToken);
                if (ajaxResult.Success == false)
                {
                    if (string.IsNullOrEmpty(ajaxResult.Message))
                    {
                        var r = new AjaxResult<List<LoginInfo>>();
                        r.Success = false;
                        r.Message = "提交参数错误,未获取到AccessToken";
                        r.Total = (int)EnumTotal.Token错误;
                        ContentResult cr = new ContentResult();
                        cr.Content = r.ExToJson();
                        context.Result = cr;
                    }
                    else
                    {
                        var r = new AjaxResult<List<LoginInfo>>();
                        r.Success = false;
                        r.Message = ajaxResult.Message;
                        r.Total = (int)EnumTotal.Token错误;
                        ContentResult cr = new ContentResult();
                        cr.Content = r.ExToJson();
                        context.Result = cr;
                    }
                    return;
                }
                await NextDo(context, next);
                return;
            }

            #endregion

            #region 是否包含ExOnlyValidateOpenID

            type = typeof(ExOnlyValidateOpenID);
            isDefined = controllerActionDescriptor.ControllerTypeInfo.CustomAttributes.Any(m => m.AttributeType == type)
                             || controllerActionDescriptor.MethodInfo.CustomAttributes.Any(m => m.AttributeType == type);
            if (isDefined)
            {
                if (PcLoginedBll.CurrentOpenID == null)
                {
                    AjaxResult<List<LoginInfo>> ar = new AjaxResult<List<LoginInfo>>();
                    ar.Message = $"{lan(context).GetString("ActionFilter.LoginExpired")}";
                    ar.Total = (int)EnumTotal.WeChatToken错误;
                    ContentResult cr = new ContentResult();
                    cr.Content = ar.ExToJson();
                    context.Result = cr;
                    return;
                }

                await NextDo(context, next);
                return;
            }

            #endregion

            #region 登录验证

            if (PcLoginedBll.CurrentEmployee == null || PcLoginedBll.CurrentEmployee.SysEmployeeID <= 0 || PcLoginedBll.CurrentRights == null || PcLoginedBll.CurrentStore == null)
            {
                var bll = new SysEmployeeBll();
                var r = bll.LoginByToken(PcLoginedBll.Token, true);
                if (r.Success == false)
                {
                    bool isAjax = context.HttpContext.Request.ExIsAjaxRequest();
                    if (isAjax)
                    {
                        //登录失效,请退出重新登录!
                        r.Message += $" {lan(context).GetString("ActionFilter.LoginExpired")}";
                        r.Total = (int)EnumTotal.帐号过期;
                        ContentResult cr = new ContentResult();
                        cr.Content = r.ExToJson();
                        context.Result = cr;
                        return;
                    }
                    else
                    {
                        string loginUrl = "/pages/login";
                        ContentResult cr = new ContentResult();
                        cr.Content = $"<script>alert('{lan(context).GetString("ActionFilter.LoginExpired")}');top.location.href='{loginUrl}';</script>";
                        context.Result = cr;
                        return;
                    }
                }
            }

            #endregion

            #region OpenID自动绑定用户信息

            if (PcLoginedBll.CurrentEmployee != null)
            {
                SysEmployeeOpenIDBll.Bind(PcLoginedBll.CurrentEmployee.SysEmployeeID);
            }

            #endregion

            #region 是否包含OnlyValidateSysEmployee

            type = typeof(ExOnlyValidateSysEmployee);
            isDefined = controllerActionDescriptor.ControllerTypeInfo.CustomAttributes.Any(m => m.AttributeType == type)
                    || controllerActionDescriptor.MethodInfo.CustomAttributes.Any(m => m.AttributeType == type);
            if (isDefined)
            {
                await NextDo(context, next);
                return;
            }

            #endregion

            #region 验证权限

            string currentUrl = SysOperateLogBll.GetUrl(context);
            if (string.IsNullOrEmpty(currentUrl))
            {
                var r = new AjaxResult<string>();
                r.Success = false;
                r.Message = $"{lan(context).GetString("ActionFilter.PowerNoUrl")}";//"权限判断错误:未获取到当前请求ajax路径";
                ContentResult cr = new ContentResult();
                cr.Content = r.ExToJson();
                context.Result = cr;
                return;
            }
            var currentRights = PcLoginedBll.CurrentRightsUrls;
            bool has = currentRights.Any(m => m.Contains(currentUrl));
            if (has == false)
            {
                var r = new AjaxResult<string>();
                r.Success = false;
                //r.Total = (int)EnumTotal.用户信息及权限重新加载;//这里是没有权限信息
                r.Message = $"{lan(context).GetString("ActionFilter.NoPower")}"; //"您没有此访问权限";
                ContentResult cr = new ContentResult();
                cr.Content = r.ExToJson();
                context.Result = cr;
                return;
            }

            #endregion

            await NextDo(context, next);
        }

        private async Task NextDo(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            #region 是否记录用户操作日志

            var resultContext = await next();
            //ViewResult是页面返回的
            var actionResult = resultContext.Result;
            if (actionResult is not ObjectResult result) return;
            var resultObj = result.Value;
            if (resultObj is not AjaxResult ar) return;
            //成功的,或异常的
            bool isError = ar.Success == false && ar.Total == (int)EnumTotal.异常;
            if (ar.Success || isError)
            {
                //用户操作日志记录
                SysOperateLogBll.DealSysOperateLog(context, isError, ar);
            }

            #endregion
        }

        private LanguageHelper lan(ActionExecutingContext context)
        {
            var lan = LanguageHelper.GetInstance(context.HttpContext.Session.Id);
            return lan;
        }

        #endregion

        #region 设置多语言,登录信息(权限验证)获取与验证

        ///// <summary>
        ///// MVC和webApi都走这里,验证写在这里
        ///// </summary>
        ///// <param name="filterContext"></param>
        //public override void OnActionExecuting(ActionExecutingContext filterContext)
        //{
        //    //设置多语言
        //    LanguageHelper.SetLanguage();
        //    var lan = LanguageHelper.GetInstance(filterContext.HttpContext.Session.Id);
        //    var isDefined = false;//是否是不做登录判断的 AllowAnonymousAttribute
        //    var controllerActionDescriptor = filterContext.ActionDescriptor as ControllerActionDescriptor;
        //    if (controllerActionDescriptor != null)
        //    {
        //        var type = typeof(AllowAnonymousAttribute);
        //        isDefined =
        //            controllerActionDescriptor.ControllerTypeInfo.GetCustomAttributes(true)
        //                .Any(a => a.GetType() == type || controllerActionDescriptor
        //                    .MethodInfo.GetCustomAttributes(inherit: true)
        //                    .Any(a => a.GetType() == type));
        //    }
        //    if (isDefined)
        //    {
        //        base.OnActionExecuting(filterContext);
        //        return;
        //    }
        //    var token = PcLoginedBll.Token;
        //    if (string.IsNullOrWhiteSpace(token))
        //    {
        //        var item = new ContentResult();
        //        item.Content = $" {lan.GetString("ActionFilter.NoLoginInfo")}";//"没有登录信息";
        //        filterContext.Result = item;
        //        base.OnActionExecuting(filterContext);
        //        return;
        //    }

        //    #region 登录验证

        //    if (PcLoginedBll.CurrentEmployee == null || PcLoginedBll.CurrentEmployee.SysEmployeeID <= 0 || PcLoginedBll.CurrentRights == null)
        //    {
        //        var bll = new SysEmployeeBll();
        //        var r = bll.LoginByToken(token, true);
        //        if (r.Success == false)
        //        {
        //            bool isAjax = filterContext.HttpContext.Request.ExIsAjaxRequest();
        //            if (isAjax)
        //            {
        //                //登录失效,请退出重新登录!
        //                r.Message += $" {lan.GetString("ActionFilter.LoginExpired")}";
        //                r.Total = (int)EnumTotal.帐号过期;
        //                ContentResult cr = new ContentResult();
        //                cr.Content = r.ExToJson();
        //                filterContext.Result = cr;
        //                return;
        //            }
        //            else
        //            {
        //                string loginUrl = "/pages/login";
        //                ContentResult cr = new ContentResult();
        //                cr.Content = $"<script>alert('{lan.GetString("ActionFilter.LoginExpired")}');top.location.href='{loginUrl}';</script>";
        //                filterContext.Result = cr;
        //                return;
        //            }
        //        }
        //    }

        //    #endregion

        //    #region 是否包含OnlyValidateSysEmployee

        //    if (controllerActionDescriptor != null)
        //    {
        //        var type = typeof(ExOnlyValidateSysEmployee);
        //        isDefined =
        //            controllerActionDescriptor.ControllerTypeInfo.GetCustomAttributes(true)
        //                .Any(a => a.GetType() == type || controllerActionDescriptor
        //                    .MethodInfo.GetCustomAttributes(inherit: true)
        //                    .Any(a => a.GetType() == type));
        //    }

        //    if (isDefined)
        //    {
        //        base.OnActionExecuting(filterContext);
        //        return;
        //    }

        //    #endregion

        //    #region 验证权限

        //    string currentUrl = null;
        //    if (controllerActionDescriptor != null)
        //    {
        //        currentUrl = controllerActionDescriptor.AttributeRouteInfo?.Template;
        //        if (string.IsNullOrEmpty(currentUrl))
        //        {
        //            string action = filterContext.ActionDescriptor.RouteValues["action"];
        //            string controller = filterContext.ActionDescriptor.RouteValues["controller"];
        //            currentUrl = $"api/{controller}/{action}";
        //        }
        //        else
        //        {
        //            if (currentUrl.IndexOf("/", StringComparison.Ordinal) == 0)
        //            {
        //                currentUrl = currentUrl.Substring(1);
        //            }
        //        }
        //    }
        //    if (string.IsNullOrEmpty(currentUrl))
        //    {
        //        var r = new AjaxResult<string>();
        //        r.Success = false;
        //        r.Message = $"{lan.GetString("ActionFilter.PowerNoUrl")}";//"权限判断错误:未获取到当前请求ajax路径";
        //        ContentResult cr = new ContentResult();
        //        cr.Content = r.ExToJson();
        //        filterContext.Result = cr;
        //        return;
        //    }
        //    var currentRights = PcLoginedBll.CurrentRightsUrls;
        //    bool has = currentRights.Any(m => m.Contains(currentUrl));
        //    if (has == false)
        //    {
        //        var r = new AjaxResult<string>();
        //        r.Success = false;
        //        //r.Total = (int)EnumTotal.用户信息及权限重新加载;//这里是没有权限信息
        //        r.Message = $"{lan.GetString("ActionFilter.NoPower")}"; //"您没有此访问权限";
        //        ContentResult cr = new ContentResult();
        //        cr.Content = r.ExToJson();
        //        filterContext.Result = cr;
        //        return;
        //    }

        //    #endregion

        //    base.OnActionExecuting(filterContext);
        //}

        ///// <summary>
        ///// 
        ///// </summary>
        //public class NoPermissionRequiredAttribute : ActionFilterAttribute
        //{
        //    /// <summary>
        //    /// 
        //    /// </summary>
        //    /// <param name="filterContext"></param>
        //    public override void OnActionExecuting(ActionExecutingContext filterContext)
        //    {
        //        base.OnActionExecuting(filterContext);
        //    }
        //}

        #endregion
    }
}
